#ifndef OPT_H_INCLUDED
#define OPT_H_INCLUDED

#include "cmodel.h"
/*
 * structure for the gsl optimization routine
 *
 */
namespace buola { namespace hdp {
    
class CVarPhiFunc
{
public:
    CVarPhiFunc(int pNumClasses,int pLabel,int pTotal,const mat::CMat_d &pMu,const mat::CMat_d &pPhi,const mat::CVec_d &pMatCounts,
                const mat::CMat_d &pELogBetaDocCounts,const mat::CVec_d &pELogSticks1st,double pPenalty);
    
    double F(const mat::CMat_d &pX);
    mat::CMat_d DF(const mat::CMat_d &pX);
    double RowConstraint(const mat::CMat_d &pX,int pRow);
    
    std::pair<double,mat::CMat_d> FDF(const mat::CMat_d &pX)
    {
        return {F(pX),DF(pX)};
    }

private:
    int mNumClasses;
    int mLabel;
    int mTotal;
    const mat::CMat_d &mMu;
    const mat::CMat_d &mPhi;
    const mat::CVec_d &mMatCounts;
    const mat::CMat_d &mELogBetaDocCounts;
    const mat::CVec_d &mELogSticks1st;
//    double mPenalty;
};

class CSoftMaxFunc
{
public:
    CSoftMaxFunc(const CLabelStats &pSS,const CCorpus &pCorpus,const std::vector<int> &pIndices,double pPenalty);
    
    double F(const mat::CMat_d &pX);
    mat::CMat_d DF(const mat::CMat_d &pX);
    
    std::pair<double,mat::CMat_d> FDF(const mat::CMat_d &pX)
    {
        return {F(pX),DF(pX)};
    }

private:
    const CLabelStats &mSS;
    const CCorpus &mCorpus;
    const std::vector<int> &mIndices;
    double mPenalty;
};

/*namespace hdp*/ } /*namespace buola*/ }

#endif // OPT_H_INCLUDED
